import math
import re
import time
import string
import random
from datetime import datetime

import numpy
from hashids import Hashids


class Helper:
    # 流水号
    @staticmethod
    def order_sn() -> str:
        data_str = datetime.now().strftime("%Y%m%d%H%M%S")
        return data_str + str(random.randint(10**5, 10**6 - 1))

    @staticmethod
    def letter_alphabet(num: int = 1) -> str:
        index_s = ''
        while (num > 0):
            m = num % 26
            if m == 0:
                m = 26
            index_s = chr(m + 64) + index_s
            num = math.floor((num - m) / 26)
        return index_s

    @staticmethod
    def batch_sn_encode(num: int = 1, num_length: int = 4) -> str:
        if num < 0:
            raise Exception('Number can\'t be less than 0')
        number = num % 10**num_length
        alpha_num = num // 10**num_length + 1
        alpha = Helper.letter_alphabet(alpha_num).lower()
        return alpha + str(number).zfill(num_length)

    @staticmethod
    def batch_sn_decode(batch_sn: str = 'a0000', num_length: int = 4) -> int:
        alpha_pattern = re.compile('^([a-z]+)')
        num_pattern = re.compile('(\d+)$')
        alpha = alpha_pattern.findall(batch_sn)
        num = num_pattern.findall(batch_sn)
        if len(alpha) == 0 or len(num) == 0:
            raise Exception('Number can\'t be less than 0')
        if len(num) != num_length:
            num_length = len(num)
        alpha = alpha[0].upper()
        start_index = 1
        start_alpha = 'A'
        while (alpha != start_alpha):
            start_index += 1
            start_alpha = Helper.letter_alphabet(start_index)
        num = (10**num_length * (start_index - 1)) + int(num[0])
        return num

    @staticmethod
    def random_int(length: int = 9, dtype=numpy.uint64):
        low = (10**(length - 1))
        high = (10**length) - 1
        list_int = numpy.random.randint(low=low, high=high, size=1, dtype=dtype)
        return int(list_int[0])

    @staticmethod
    def serial_number(number: int = 1, length: int = 6) -> str:
        f = '{:0=' + str(length) + '}'
        return f.format(number)

    @staticmethod
    def get_define_str(str_type):
        type = int(str_type)
        _str = ''
        if type == 1:
            # 1 随机数字
            # _str = '0123456789'
            _str = string.digits
        elif type == 2:
            # 2 大写字母
            # _str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
            _str = string.ascii_uppercase
        elif type == 3:
            # 3 小写字母
            # _str = 'abcdefghijklmnopqrstuvwxyz'
            _str = string.ascii_lowercase
        elif type == 4:
            # 4 大小写字母
            # _str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
            # _str = string.ascii_uppercase + string.ascii_lowercase
            _str = string.ascii_letters
        elif type == 5:
            # 5 大写字母数字
            # _str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
            _str = string.ascii_uppercase + string.digits
        elif type == 6:
            # 6 小写字母数字
            # _str = 'abcdefghijklmnopqrstuvwxyz0123456789'
            _str = string.ascii_lowercase + string.digits
        elif type == 7:
            # 7 大小写字母数字
            # _str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
            # _str = string.ascii_uppercase + string.ascii_lowercase + string.digits
            _str = string.ascii_letters + string.digits
        elif type == 8:
            # 8 大小写字母数字特殊字符
            # _str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+=-'
            _str = string.ascii_letters + string.digits + '!@#$%^&*()_+=-'
        return _str

    @staticmethod
    def random_hash_str(number=1, length=8, salt='code', ctype=0) -> str:
        """
        hashids 随机字符串
        """
        if ctype < 2:
            raise 'random str is integer'
        alphabet = Helper.get_define_str(ctype)

        hashids = Hashids(salt=salt, min_length=length, alphabet=alphabet)
        return hashids.encode(number)

    @staticmethod
    def random_str(length=8, ctype=1) -> str:
        alphabet = Helper.get_define_str(ctype)
        return random.sample(alphabet, length)


__all__ = (
    'Helper',
)
